using System;
using FireStarter.Base;
using FireStarterModeller.BO;
using Habanero.Util;

namespace FireStarter.CodeGeneration
{
    /// <summary>
    /// Generates the clauses to be inserted in templates to generate valid sample
    /// values for properties.  Where possible the values are intended to provide
    /// a spread of random possible values.
    /// </summary>
    public class ValidValueGenerator
    {
        private static string _className;

        public static string GetValidValue(IModelProperty modelProperty)
        {
            IModelRelationship relationship = CheckPropertyInRelationship(modelProperty);
            if (relationship != null && !relationship.IsMultiple && relationship.GenerateCode)
            {
                return GetRelatedPropertyValidValue(relationship);
            }

            if (modelProperty.PropertyType == null ||modelProperty.PropertyType.PropertyTypeName == null ||modelProperty.PropertyType.AssemblyName == null)
            {
                return "null";
            }
            string upper = modelProperty.Parent.ToString();
            _className = StringUtilities.ToLowerFirstLetter(upper) + "1";
            string validValue = "factory.GetValidPropValue(" + _className + "=>" + _className + "." + modelProperty.PropertyName + ")";
            return validValue;
        }

        private static IModelRelationship CheckPropertyInRelationship(IModelProperty modelProperty)
        {
            if (modelProperty.Parent == null) return null;

            IModelClass modelClass = (IModelClass)modelProperty.Parent;
            foreach (IModelRelationship modelRelationship in modelClass.AllRelationships)
            {
                if (modelRelationship.Property.PropertyName == modelProperty.PropertyName)
                {
                    return modelRelationship;
                }
            }
            return null;
        }

        private static string GetRelatedPropertyValidValue(IModelRelationship relationship)
        {
            string relatedClassName = relationship.RelatedClass;
            return string.Format("(({0})factory.GetValidRelationshipValue({1}=>{2}.{3})).{4}", relatedClassName, _className, _className, relationship.RelationshipName, relationship.RelatedProperty.PropertyName);
        }
/*
        // This is a little fragile, but gets the job done (ie. what if the class/prop names are constructed differently?)
        private static string GetValidValueForLookup(IModelProperty modelProperty, string type)
        {
            string lastPart =
                String.Format(
                    @"TestUtilsShared.GetRandomLookupListValue({0}.Props[""{1}""].PropDef.LookupList.GetLookupList())",
                    StringUtilities.ToLowerFirstLetter(((IModelClass)modelProperty.Parent).ClassName), modelProperty.PropertyName);

            switch (modelProperty.LookupListType)
            {
                case ModelLookupType.Simple:
                    if (type == "System.String") return String.Format("({0}) {1}", type, lastPart);
                    else return String.Format("{0}.Parse((System.String){1})", type, lastPart);
                case ModelLookupType.BusinessObject:
                    if (type == "System.Guid")
                        return String.Format("new Guid({0})", lastPart);
                    //    return String.Format("((BusinessObject){0}).ID.GetAsGuid()", lastPart);
                    if (type == "System.String")
                        return String.Format("{0}", lastPart);
                    //    return String.Format("((BusinessObject){0}).ID.GetObjectId()", lastPart);
                    return String.Format("({0}) Convert.ChangeType({1},typeof({0}))", type, lastPart);
                case ModelLookupType.Database:
                    break;
                default:
                    throw new ArgumentOutOfRangeException("modelProperty", "Lookup list type not recognised in valid value");
            }
            return "";
        }*/
    }
}